package huoshan

import (
	"bytes"
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"encoding/hex"
	"errors"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"
)

const (
	Path    = "/" // 路径，不包含 Query
	Region  = "cn-beijing"
	Version = "2018-01-01"
)

func F保存base64图片(filename string, imageData string) error {
	// 解码base64图片数据
	decodedData, err := base64.StdEncoding.DecodeString(imageData)
	if err != nil {
		return err
	}

	// 将解码后的数据写入文件os.WriteFile(filename, data, perm)
	if err := os.WriteFile(filename, decodedData, os.ModePerm); err != nil {
		return err
	}
	return nil
}

func (a *HsClent) F发送请求(method, addr, service string, sts *Credentials, queries url.Values, body []byte) (by []byte, err error) {

	requestAddr := fmt.Sprintf("%s%s?%s", addr, Path, queries.Encode())
	request, err := http.NewRequest(method, requestAddr, bytes.NewBuffer(body))
	if err != nil {
		err = fmt.Errorf("bad request: %w", err)
		return
	}

	if sts != nil {
		request.Header.Set("X-Security-Token", sts.SessionToken)
	}

	now := time.Now()
	date := now.UTC().Format("20060102T150405Z")
	authDate := date[:8]
	request.Header.Set("X-Date", date)

	payload := hex.EncodeToString(hashSHA256(body))
	request.Header.Set("X-Content-Sha256", payload)
	if service == "sts" {
		request.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	} else {
		request.Header.Set("Content-Type", "application/json")

	}

	queryString := strings.Replace(queries.Encode(), "+", "%20", -1)
	signedHeaders := []string{"host", "x-date", "x-content-sha256", "content-type"}
	var headerList []string
	for _, header := range signedHeaders {
		if header == "host" {
			headerList = append(headerList, header+":"+request.Host)
		} else {
			v := request.Header.Get(header)
			headerList = append(headerList, header+":"+strings.TrimSpace(v))
		}
	}
	headerString := strings.Join(headerList, "\n")

	canonicalString := strings.Join([]string{
		method,
		Path,
		queryString,
		headerString + "\n",
		strings.Join(signedHeaders, ";"),
		payload,
	}, "\n")
	//log.Printf("canonical string:\n%s\n", canonicalString)

	hashedCanonicalString := hex.EncodeToString(hashSHA256([]byte(canonicalString)))
	//log.Printf("hashed canonical string: %s\n", hashedCanonicalString)

	credentialScope := authDate + "/" + Region + "/" + service + "/request"
	signString := strings.Join([]string{
		"HMAC-SHA256",
		date,
		credentialScope,
		hashedCanonicalString,
	}, "\n")

	ak := a.AccessKeyID
	if sts != nil {
		ak = sts.AccessKeyId
	}
	sk := a.AccessKeySecret
	if sts != nil {
		sk = sts.SecretAccessKey
	}
	// 3. 构建认证请求头
	signedKey := getSignedKey(sk, authDate, Region, service)
	signature := hex.EncodeToString(hmacSHA256(signedKey, signString))

	authorization := "HMAC-SHA256" +
		" Credential=" + ak + "/" + credentialScope +
		", SignedHeaders=" + strings.Join(signedHeaders, ";") +
		", Signature=" + signature
	request.Header.Set("Authorization", authorization)

	response, err := http.DefaultClient.Do(request)
	if err != nil {
		return
	}
	// 5. 打印响应
	if response.StatusCode == 200 {
		by, err = io.ReadAll(response.Body)
	} else {
		by, _ = io.ReadAll(response.Body)
		err = errors.New("请求失败")
	}
	return
}

func hmacSHA256(key []byte, content string) []byte {
	mac := hmac.New(sha256.New, key)
	mac.Write([]byte(content))
	return mac.Sum(nil)
}

func getSignedKey(secretKey, date, region, service string) []byte {
	kDate := hmacSHA256([]byte(secretKey), date)
	kRegion := hmacSHA256(kDate, region)
	kService := hmacSHA256(kRegion, service)
	kSigning := hmacSHA256(kService, "request")
	return kSigning
}

func hashSHA256(data []byte) []byte {
	hash := sha256.New()
	if _, err := hash.Write(data); err != nil {
		log.Printf("input hash err:%s", err.Error())
	}

	return hash.Sum(nil)
}
